package frame

import (
	"fmt"
	"os"
	"strings"

	"github.com/goccy/go-yaml"
)

type mySQLConfig struct {
	Host     string `yaml:"host"`     // MySQL 的 host 是字符串类型
	Port     int    `yaml:"port"`     //  MySQL 的 port 是数字类型
	User     string `yaml:"user"`     // MySQL 的 user 是字符串类型
	Password string `yaml:"password"` // MySQL 的 password 是字符串类型
	Database string `yaml:"database"` // MySQL 的 database 是字符串类型
}

type redisConfig struct {
	Host     string `yaml:"host"`     // Redis 的 host 是字符串类型
	Port     int    `yaml:"port"`     //  Redis 的 port 是数字类型
	Password string `yaml:"password"` // Redis 的 password 是字符串类型
	Database int    `yaml:"database"` // Redis 的 database 是数字类型
}

type sqliteConfig struct {
	Path string `yaml:"path"` // SQLite 数据库路径
}

// 应用数据库配置
type AppDatabase struct {
	MySQL  *mySQLConfig  `yaml:"mysql"`  // MySQL 数据库配置
	Redis  *redisConfig  `yaml:"redis"`  // Redis 数据库配置
	SQLite *sqliteConfig `yaml:"sqlite"` // SQLite 数据库配置
}

// 应用服务器配置
type serverConfig struct {
	Env              string `yaml:"env"`              // 环境标识（dev/test/prod）
	Port             int    `yaml:"port"`             // 服务器端口
	Static           string `yaml:"static"`           // 静态文件目录
	Database         string `yaml:"database"`         // 数据库类型（mysql/sqlite）
	Cache            string `yaml:"cache"`            // 缓存类型（redis/memory/file）
	Log              string `yaml:"log"`              // 日志文件路径
	Token_secret_key string `yaml:"token_secret_key"` // token密钥
}

type config struct {
	Server   *serverConfig `yaml:"server"`   // 服务器配置
	Database *AppDatabase  `yaml:"database"` // 数据库配置
}

var Config *config = &config{
	Database: &AppDatabase{
		MySQL:  &mySQLConfig{},  // MySQL 数据库配置
		Redis:  &redisConfig{},  // Redis 数据库配置
		SQLite: &sqliteConfig{}, // SQLite 数据库配置
	},
	Server: &serverConfig{},
}

func init() {
	loadDefaults()

	{
		err := ParseYaml("config/database.yaml", Config.Database)
		if err != nil {
			panic(err)
		}
	}
	{
		err := ParseYaml("config/server.yaml", Config.Server)
		if err != nil {
			panic(err)
		}
	}

	// 初始化目录
	if err := EnsureDirectoryExists(Config.Server.Log); err != nil {
		panic(err)
	}
	if err := EnsureDirectoryExists(Config.Server.Static); err != nil {
		panic(err)
	}
	if err := EnsureDirectoryExists(Config.Database.SQLite.Path); err != nil {
		panic(err)
	}
}

func loadDefaults() {
	randSre, err := RandomString(64)
	if err != nil {
		randSre = "e28ddaff9faa9da62b63c137b36041178efs8s7a55b69f94b26f7f49817c1000"
	}
	// 设置合理的默认值
	Config.Server = &serverConfig{
		Env:              "dev",
		Port:             8080,
		Static:           "static/",
		Database:         "sqlite",
		Cache:            "file", // 缓存类型（redis/memory/file）
		Log:              "logs/Request.log",
		Token_secret_key: "Yoyo123-" + strings.ToLower(randSre),
	}

	Config.Database = &AppDatabase{
		MySQL: &mySQLConfig{
			Host:     "localhost",
			Port:     3306,
			User:     "root",
			Password: "",
			Database: "myapp",
		},
		Redis: &redisConfig{
			Host:     "localhost",
			Port:     6379,
			Password: "",
			Database: 0,
		},
		SQLite: &sqliteConfig{
			Path: "database/data.db",
		},
	}

	// 初始化目录
	if err := EnsureDirectoryExists("config/"); err != nil {
		panic(err)
	}

	// 初始化database.yaml
	if isExist := FileExists("config/database.yaml"); !isExist {
		err := StructToYaml("config/database.yaml", Config.Database)
		if err != nil {
			panic(err)
		}
	}
	// 初始化server.yaml
	if isExist := FileExists("config/server.yaml"); !isExist {
		err := StructToYaml("config/server.yaml", Config.Server)
		if err != nil {
			panic(err)
		}
	}
}

// ParseYaml 带解析YAML文件
func ParseYaml(yamlPath string, myStruct any) error {
	// 读取文件内容
	data, err := os.ReadFile(yamlPath)
	if err != nil {
		return fmt.Errorf("读取文件失败: %w", err)
	}

	decoder := yaml.NewDecoder(strings.NewReader(string(data)))
	if err := decoder.Decode(myStruct); err != nil {
		return fmt.Errorf("解析YAML失败: %w", err)
	}

	return nil
}

// StructToYaml 生成YAML文件
func StructToYaml(yamlPath string, myStruct any) error {
	// 序列化配置
	opts := []yaml.EncodeOption{
		yaml.Indent(2), // 设置缩进为2空格
	}

	// 执行序列化
	data, err := yaml.MarshalWithOptions(myStruct, opts...)
	if err != nil {
		return fmt.Errorf("生成YAML失败: %w", err)
	}

	// 写入文件
	if err := os.WriteFile(yamlPath, data, 0644); err != nil {
		return fmt.Errorf("写入文件失败: %w", err)
	}

	return nil
}
